import configparser
import ctypes
import json
import logging
import os
import random
import re
import shutil
import sys
import tempfile
import threading
import time
import traceback
from datetime import datetime
from http import HTTPStatus
from io import StringIO
from tkinter import ttk, messagebox
from urllib.parse import unquote
import tkinter as tk
import tkinter.messagebox
import pystray
import pyautogui
import pygetwindow as gw
import urllib3
import win32con
import win32gui
from pystray import MenuItem as item
from apscheduler.triggers.cron import CronTrigger
from PIL import Image
import dashscope
from selenium.common.exceptions import WebDriverException, NoSuchElementException
from selenium.webdriver.common.keys import Keys
from apscheduler.schedulers.blocking import BlockingScheduler
import web
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from common import get_user_agent, clear_tmp_and_rust, fuzzy_search_folder_by_time, \
    get_one_comment_by_weight, ConfigChecker, create_user_agent

# app_name
app_name = f'神农'
version = f'v0.4.5'

setting = configparser.ConfigParser()
setting.read(['setting.ini'], encoding='utf-8')

# 日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 创建一个自定义格式的Formatter
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

# 创建一个FileHandler并将自定义格式的Formatter应用到它上面
file_handler = logging.FileHandler(f'log/{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.log', encoding='utf-8')
file_handler.setFormatter(formatter)
# 实时写入文件
# file_handler.flush = True
# 将FileHandler添加到日志记录器中
logger = logging.getLogger()
logger.addHandler(file_handler)

# 计算屏幕中央位置
screenWidth, screenHeight = pyautogui.size()
centerX = int(screenWidth / 2)
centerY = int(screenHeight / 2)


def get_comment_other1(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    comment_list_elements = element.find_elements_by_xpath('.//div[@data-e2e="comment-item"]')
    comment_other = ''
    for element_item in comment_list_elements:
        comment_new = element_item.find_element_by_xpath('.//div[2]/div[1]/div[2]').text
        comment_new = comment_new.replace('作者赞过', '')
        comment_new = comment_new.replace('作者回复过', '')
        comment_new = comment_new.replace('置顶', '')
        comment_new = re.sub(r"@(.*?) ", '', comment_new)
        comment_new = comment_new.strip()
        if comment_new.strip() != '':
            comment_other = comment_other + comment_new + '\n'
    return comment_other.strip()


def get_comment_other(driver, gpt_type=2):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    comment_list_elements = element.find_elements_by_xpath('.//div[@data-e2e="comment-item"]')
    comment_other = []
    for element_item in comment_list_elements:
        comment_new = element_item.find_element_by_xpath('.//div[2]/div[1]/div[2]').text
        comment_new = comment_new.replace('作者赞过', '')
        comment_new = comment_new.replace('作者回复过', '')
        comment_new = comment_new.replace('置顶', '')
        comment_new = re.sub(r"@(.*?) ", '', comment_new)
        if comment_new.strip() == '':
            continue

        comment_other.append(
            [
                comment_new.strip(),
                indicator(element_item.find_element_by_xpath('.//div[2]/div[1]/div[4]/div[1]/div[1]').text),
            ]
        )

        # comment_new = comment_new
        # if comment_new.strip() != '':
        #     comment_other = comment_other + comment_new + '\n'
    comment_other_str = ''
    if len(comment_other) > 0:
        comment_other = sorted(comment_other, key=lambda x: x[1], reverse=True)
        if gpt_type == 2:
            if '置顶' in comment_other[0][0]:
                if len(comment_other) == 1:
                    comment_other_str = ''
                else:
                    del comment_other[0][0]

            for item in comment_other:
                if len(item[0].encode('utf-8')) > 10:
                    comment_other_str = item[0]
                    break
        else:
            comment_other_str = '\n'.join([every[0] for every in comment_other])
            # logger.info(comment_other_str)
    return comment_other_str


def get_video_tip(driver, title=''):
    comment_other = get_comment_other(driver, 1)
    if comment_other == '':
        return ''
    if title != '':
        comment_other = title.replace(' #', '') + '\n' + comment_other
    # tip_ai = call_tips_with_messages(comment_other)
    gpt_tips = config.get('Ai', 'ai_video_tip_prompt', fallback=[])
    # logger.info(f'给gpt的所有tips {gpt_tips}, gpt会在这里边挑')
    status, tip_ai = web.user_tips(comment_other, gpt_tips)
    logger.info(f'****** gpt给的tip： {tip_ai}')
    if not status or tip_ai is None or len(tip_ai) > 500:
        tip = ''
    else:
        tip = tip_ai
    return tip


def get_comment_from_gpt(driver, title=''):
    gpt_type = config.getint('Comment', 'comment_gpt_type', fallback=2)
    comment_other = get_comment_other(driver, gpt_type)
    if comment_other == '':
        return ''
    # logger.info(f'****** 别人的回复： {comment_other}')
    # comment_ai = call_comment_with_messages(comment_other)
    if gpt_type == 1:
        # 多条评论模式
        if title != '':
            comment_other = title.replace(' #', '') + '\n' + comment_other
        status, comment = web.user_infer(comment_other, config.get('Comment', 'comment_style', fallback=''))
    else:
        # 单条评论模式
        status, comment = web.user_transfer(comment_other)
        logger.info(f'****** ai给的回复{comment}')
    if not status:
        comment = ''
    if comment is None or len(comment) > 500:
        comment = ''

    # 评论过滤
    if comment != '':
        comment = comment.replace('AI', '永乐大帝')
        comment = comment.replace('ai', '永乐大帝')
        comment = comment.replace('Ai', '永乐大帝')
        comment = comment.replace('机器人', '永乐大帝')
        if comment[0] == '"':
            comment = comment[1:]
        if comment[-1] == '"':
            comment = comment[:-1]

        if comment[0] == '“':
            comment = comment[1:]
        if comment[-1] == '”':
            comment = comment[:-1]
    logger.info(f'****** 即将回复{comment}')
    return comment


def get_comment_from_local(driver):
    comment = file_get_one_comment_by_weight()
    if coin(config.getfloat('Comment', 'comment_local_transfer_rate', fallback=0.0)):
        logger.info(f'本地评论transfer模式')
        status, comment = web.user_transfer(comment)
        logger.info(f'****** ai给的回复： {comment}')
    else:
        logger.info(f'本地评论模式')
        logger.info(f'****** 本地给的回复： {comment}')
    logger.info(f'****** 即将回复{comment}')
    return comment


def get_account_name(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    account_element = element.find_element(By.CLASS_NAME, 'account-name')
    return account_element.text


def get_my_account_nickname(driver):
    try:
        content = driver.execute_script("return document.getElementById('RENDER_DATA').innerHTML")
        content = json.loads(unquote(content))
        return content['app']['user']['info']['nickname']

    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())
    return ''


def get_my_account_did(driver):
    try:
        content = driver.execute_script("return document.getElementById('RENDER_DATA').innerHTML")
        content = json.loads(unquote(content))
        return content['app']['user']['info']['shortId']

    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())
    return ''


def get_account_href(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//a[@data-e2e="video-avatar"]')
    href = element.get_attribute('href')
    return href


def get_like_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="video-player-digg"]')
    return indicator(element.text)


def get_comment_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="feed-comment-icon"]')
    return indicator(element.text)


def get_collection_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="video-player-collect"]')
    return indicator(element.text)


def get_share_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="video-player-share"]')
    return indicator(element.text)


def get_video_id(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    return element.get_attribute("data-e2e-vid")


def get_video_duration(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//span[@class="time-duration"]')
    return play_time_to_duration(element.text)


def get_video_desc(driver):
    try:
        element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())
        return '', False, True

    element = element.find_element_by_xpath('.//div[@data-e2e="video-desc"]')
    is_ad = False
    str = element.text.strip()
    if str.endswith('广告'):
        str = element.text.replace('广告', '')
        is_ad = True
    return str, is_ad, False


def submit_comment(driver, content='这...'):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.CLASS_NAME, 'DraftEditor-root')
    # element.click()
    # time.sleep(1)
    mouse = ActionChains(driver)
    mouse.move_to_element(element).click().send_keys(f'{content}').send_keys(Keys.ENTER).perform()


def add_like_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="video-player-digg"]')
    element.click()


def add_collection_count(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element_by_xpath('.//div[@data-e2e="video-player-collect"]')
    element.click()


def show_right_bar(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.CLASS_NAME, 'slider-video')
    element = element.find_element_by_xpath("following-sibling::div[position()=1]")
    element.click()


def show_comment_panel(driver):
    check_captcha_container_mask(driver)
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.ID, 'relatedVideoCard')
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[2]")
    # element = element.find_element_by_xpath("following-sibling::div[position()=1]")
    element.click()


def show_user_works_panel(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.ID, 'relatedVideoCard')
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[1]")
    # element = element.find_element_by_xpath("following-sibling::div[position()=1]")
    element.click()


def move_notice(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="im-entry"]')
    element.click()


def move_message(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="im-entry"]')
    element.click()


def jump_user_index(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.ID, 'relatedVideoCard')
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[3]/div[1]/div[1]/div[1]")
    element = element.find_element_by_xpath('.//a[@target="_blank"]')
    # element = element.find_element_by_xpath("following-sibling::div[position()=1]")
    element.click()


def jump_my_index(driver):
    element = driver.find_element_by_xpath('//div[@data-e2e="feed-active-video"]')
    element = element.find_element(By.ID, 'relatedVideoCard')
    element = element.find_element_by_xpath(".//div[1]")
    element = element.find_element_by_xpath(".//div[3]/div[1]/div[1]/div[1]")
    element = element.find_element_by_xpath('.//a[@target="_blank"]')
    # element = element.find_element_by_xpath("following-sibling::div[position()=1]")
    element.click()


def jump_recommend(driver):
    try:
        element = driver.find_element_by_xpath('//div[@data-e2e="douyin-navigation"]')
        element = element.find_element_by_xpath(".//div[1]")
        element = element.find_element_by_xpath(".//div[1]")
        element = element.find_element_by_xpath(".//*[contains(text(), '推荐')]")
        element = element.find_element_by_xpath("..")
        element = element.find_element_by_xpath("..")
        element.click()
    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())


def search_keys(driver):
    is_new_tab = False
    try:
        check_captcha_container_mask(driver)
        keys = config.get('Search', 'search_keys', fallback='')
        if len(keys) == 0:
            return
        keys = keys.split(',')
        key = random.choice(keys)
        element = driver.find_element_by_xpath('//input[@data-e2e="searchbar-input"]')
        element.send_keys(key)
        time.sleep(2)
        element = driver.find_element_by_xpath('//button[@data-e2e="searchbar-button"]')
        element.click()
        time.sleep(9)
        check_captcha_container_mask(driver)
        # 判断是否是新tab
        all_windows = driver.window_handles
        is_new_tab = True if len(all_windows) > 1 else False
        if is_new_tab:
            current_window = driver.current_window_handle
            for window in all_windows:
                if window != current_window:
                    driver.switch_to.window(window)
                    break

        time.sleep(1)
        acc_times = 0
        max_times = random.randint(10, 20)
        element_ul = driver.find_element_by_xpath('//ul[@data-e2e="scroll-list"]')
        element_li = element_ul.find_element_by_xpath(f'.//li[1]')
        time.sleep(random.randint(30, 60))
        while True:
            check_captcha_container_mask(driver)
            acc_times = acc_times + 1
            if acc_times > max_times:
                break
            location = element_li.location
            size = element_li.size

            if '倍数' in element_li.text or '00:00' in element_li.text or '00:' in element_li.text or '图文' in element_li.text:
                logger.info(f'查看搜索视频{acc_times}次')
                # 再看0到20秒
                time.sleep(random.randint(0, 20))

                # 0.3的概率点赞
                if coin(0.3):
                    element = element_li.find_element_by_xpath('.//div[@data-e2e="video-player-digg"]')
                    element.click()

                time.sleep(random.randint(5, 10))
            else:
                logger.info(f'当前没有视频{acc_times}次')

            # print("Element location: ", location)
            # print("Element size: ", size)
            driver.execute_script("window.scrollBy({}, {});".format(location['x'], size['height']))
            # 先看随机30到60秒
            time.sleep(random.randint(30, 60))
            # 获取当前li标签，element_li是上一个，following-sibling::*后就为当前
            element_li = element_li.find_element_by_xpath("following-sibling::*")

    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())

    if is_new_tab:
        logger.info('关闭了搜索tab页')
        driver.close()
        time.sleep(2)
        all_windows = driver.window_handles
        for window in all_windows:
            logger.info('回到推荐tab页')
            driver.switch_to.window(window)
            break
        time.sleep(2)
    else:
        logger.info('还原了推荐')
        jump_recommend(driver)
        time.sleep(5)
        start_right(driver)


def search_keys2(driver):
    try:
        check_captcha_container_mask(driver)
        keys = config.get('Search', 'search_keys', fallback='')
        if len(keys) == 0:
            return
        keys = keys.split(',')
        key = random.choice(keys)
        element = driver.find_element_by_xpath('//input[@data-e2e="searchbar-input"]')
        element.send_keys(key)
        time.sleep(2)
        element = driver.find_element_by_xpath('//button[@data-e2e="searchbar-button"]')
        element.click()
        time.sleep(10)

        # element_for_height = driver.find_element(By.CLASS_NAME, 'search-result-card')
        # element_for_height = driver.find_element_by_xpath('//li[@class="search-result-card"]')
        element_ul = driver.find_element_by_xpath('//ul[@data-e2e="scroll-list"]')

        # sys.exit(0)
        acc_times = 0
        acc_height = 0
        max_times = random.randint(0, 20)
        while True:
            check_captcha_container_mask(driver)
            acc_times = acc_times + 1
            if acc_times > max_times:
                break

            # 第一步，滚动
            driver.execute_script("window.scrollTo(0, {0});".format(acc_height))
            time.sleep(5)

            # 第二步，等待加载完成，获取当前li
            element_li = element_ul.find_element_by_xpath(f'.//li[{acc_times}]')

            # 第三步，获取高度和文本
            height = driver.execute_script("return arguments[0].clientHeight;", element_li)
            acc_height = acc_height + height
            hold = element_li.text
            print(hold)
            time.sleep(5)
            # 第四步，判断是否视频
            # 如果不是视频
            if '倍数' in hold or '00:00' in hold or '00:' in hold or '图文' in hold:
                if '大家都在搜' in hold:
                    acc_height = acc_height + 58
                logger.info(f'查看搜索视频{acc_times}次')
                # time.sleep(random.randint(30, 60))
                time.sleep(3)

                # 0.3的概率点赞
                if coin(0.3):
                    element = element_li.find_element_by_xpath('.//div[@data-e2e="video-player-digg"]')
                    element.click()

                # time.sleep(random.randint(0, 30))
                time.sleep(3)
            else:
                logger.info(f'当前没有视频{acc_times}次')
                continue


    except Exception:
        logger.warning(get_error_log())


# def search_rel_():
#     # 相关搜索


def show_next_video(driver):
    check_captcha_container_mask(driver)
    try:
        element = driver.find_element(By.CLASS_NAME, 'xgplayer-playswitch-next')
        element.click()
    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())


def show_prev_video(driver):
    element = driver.find_element(By.CLASS_NAME, 'xgplayer-playswitch-prev')
    element.click()


def check_live(driver):
    try:
        driver.find_element_by_xpath('//div[@data-e2e="feed-live"]')
        logger.info('直播')
        return True
    except Exception as e:
        logger.info('非直播')
        return False


def check_second_verify_mask(driver):
    try:
        element = driver.find_element(By.CLASS_NAME, 'uc-ui-verify_header-close')
        # 随机点去验证码
        time.sleep(random.randint(1, 5))
        element.click()
        logger.info('触发了二次验证，手机号')
        return False
    except Exception as e:
        pass
    return True


acc_captcha = 0
acc_captcha_error_time = 0


def check_captcha_container_mask(driver):
    global acc_captcha
    try:
        element = driver.find_element_by_xpath('//div[@id="captcha_container"]')
        driver.execute_script("arguments[0].parentNode.removeChild(arguments[0]);", element)
        logger.info('触发了二次验证码，自动关闭(3)')
        acc_captcha = acc_captcha + 1
        return False
    except Exception as e:
        if setting.getint('System', 'check_captcha_log', fallback=0) == 1:
            logger.info(get_error_log())
        check_captcha_container_mask2(driver)
    return True


def check_captcha_container_mask2(driver):
    # captcha_container
    global acc_captcha, acc_captcha_error_time
    try:
        # element = driver.find_element_by_xpath('//div[@id="captcha_container"]/iframe')
        element = driver.find_element_by_xpath('//div[@id="captcha_container"]')
    except NoSuchElementException as e:
        if setting.getint('System', 'check_captcha_log', fallback=0) == 1:
            logger.info(get_error_log())
        return True

    try:
        element = element.find_element_by_xpath('.//iframe')
        driver.switch_to.frame(element)
        element = driver.find_element_by_xpath('//div[@class="vc-captcha-close-btn"]')
        # 随机点去验证码
        time.sleep(random.randint(1, 5))
        element.click()
        driver.switch_to.default_content()
        logger.info('触发了二次验证码，自动关闭(1)')
        acc_captcha = acc_captcha + 1
        return False
    except NoSuchElementException as e:
        if setting.getint('System', 'check_captcha_log', fallback=0) == 1:
            logger.info(get_error_log())

    try:
        element = element.find_element_by_xpath('.//div[@class="vc-captcha-close-btn"]')
        element.click()
        driver.switch_to.default_content()
        logger.info('触发了二次验证码，自动关闭(2)')
        acc_captcha = acc_captcha + 1
        return False
    except NoSuchElementException as e:
        if setting.getint('System', 'check_captcha_log', fallback=0) == 1:
            logger.info(get_error_log())

    return True


def check_by_video_tip(driver, tips, ai_tips=''):
    if tips == '':
        return True
    tips = tips.split(',')
    for tip in tips:
        if tip in ai_tips:
            return True
    return False


def check_by_count(config_value, true_count):
    config_values = config_value.split(',')
    config_values = config_values[::-1]  # 反转一次
    for one in config_values:
        one_s = one.split('-')
        if int(one_s[0]) < true_count and coin(float(one_s[1])):
            return True
    return False


def call_comment_with_messages(content):
    prompt_path = config.get('Ai', 'ai_comment_prompt')
    if not prompt_path:
        return None
    with open(prompt_path, 'r', encoding='utf-8') as f:
        prompt = f.read()
    if content == '' or content is None or prompt.strip() == '':
        return None
    content = content + '\n\n\n' + prompt
    messages = [{'role': 'system',
                 # 'content': '你现在是一个评论小能手, 我给你一些评论，根据这评论猜猜看他们在说什么主题内容，然后根据这个主题内容，你给出一条更好的评论，要求幽默，风趣，简洁字数不超过30个字，主题内容不用给我，给我评论即可'},
                 'content': '你是一个评论高手，回答风趣、幽默、简洁'},
                {'role': 'user', 'content': content}]
    dashscope.api_key = config.get('Ai', 'ai_comment_apikey')
    model = config.get('Ai', 'ai_comment_model')
    response = dashscope.Generation.call(
        # dashscope.Generation.Models.qwen_plus,
        model if model else 'qwen-turbo',
        messages=messages,
        # prompt='我给你一些评论，根据这评论猜猜看他们再说什么，这点你不用给我答案。然后针对这些评论，你给他们一条更好的评论，要求幽默，风趣，字数不超过30个字',
        # set the random seed, optional, default to 1234 if not set
        seed=random.randint(1, 10000),
        result_format='message',  # set the result to be "message" format.
    )
    if response.status_code == HTTPStatus.OK:
        if response.status_code == 200:
            return response.output.choices[0].message.content.strip('"').replace('"[', '[')
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))


def call_tips_with_messages(content):
    prompt_path = config.get('Ai', 'ai_video_tip_prompt')
    if not prompt_path:
        return None
    with open(prompt_path, 'r', encoding='utf-8') as f:
        prompt = f.read()
    if content == '' or content is None or prompt.strip() == '':
        return None
    content = content + '\n\n\n' + prompt
    messages = [
        {'role': 'user', 'content': content}]
    dashscope.api_key = config.get('Ai', 'ai_video_tip_apikey')
    model = config.get('Ai', 'ai_video_tip_model')
    response = dashscope.Generation.call(
        # dashscope.Generation.Models.qwen_plus,
        model if model else 'qwen-turbo',
        messages=messages,
        # prompt='我给你一些评论，根据这评论猜猜看他们再说什么，这点你不用给我答案。然后针对这些评论，你给他们一条更好的评论，要求幽默，风趣，字数不超过30个字',
        # set the random seed, optional, default to 1234 if not set
        seed=random.randint(1, 10000),
        result_format='message',  # set the result to be "message" format.
    )
    if response.status_code == HTTPStatus.OK:
        if response.status_code == 200:
            return response.output.choices[0].message.content.strip('"').replace('"[', '[')
    else:
        logger.info('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))


def coin(value):
    if random.random() < value:
        return True
    else:
        return False


def indicator(str):
    if '抢首评' == str:
        return 0
    if '分享' == str:
        return 0
    if '赞' == str:
        return 0
    if '收藏' == str:
        return 0
    if '万' in str:
        str = str.replace('万', '')
        return float(str) * 10000
    try:
        number = int(str)
    except Exception as e:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())
        return 0
    return number


def play_time_to_duration(play_time):
    if play_time.count(':') == 1:
        play_time = '00:' + play_time
    hours, minutes, seconds = map(int, play_time.split(':'))
    total_seconds = hours * 3600 + minutes * 60 + seconds
    return total_seconds


def seconds_to_time(seconds):
    hours = seconds // 3600
    minutes = (seconds % 3600) // 60
    seconds = seconds % 60
    return f"{hours:02d}小时{minutes:02d}分{seconds:02d}秒"


def get_error_log():
    # 创建一个StringIO对象来捕获traceback.print_exc()的输出
    trace_output = StringIO()
    traceback.print_exc(file=trace_output)
    return trace_output.getvalue()


def check_drive_active(driver):
    try:
        title = driver.title
    except WebDriverException:
        logger.info('浏览器窗口被关闭，程序退出')
        return False
    return True


def create_panel(acc_next=0, acc_view=0, acc_like=0, acc_comment=0, acc_collectio=0, acc_captcha=0, acc_time=0,
                 acc_unlike=0, my_account_nickname='', acc_jump_recommend=0, acc_search=0):
    labels = [
        f"当前用户 {my_account_nickname}",
        "----------",
        f"已点击：{acc_next}",
        f"已观看：{acc_view}",
        f"已点赞：{acc_like}",
        f"已评论：{acc_comment}",
        f"已收藏：{acc_collectio}",
        f"已运行：{seconds_to_time(int(acc_time))}",
        "----------",
        f"不符合：{acc_unlike} 不符合标签，跳过",
        f"重推荐：{acc_jump_recommend}",
        f"重搜索：{acc_search}",
        f"被验证：{acc_captcha}",
        "----------",
    ]
    return labels

def load_config():
    global config
    if not os.path.exists(f'{did_config_path}/config.ini'):
        config.read([f'default.ini', f'{did_config_path}/config.ini'], encoding='utf-8')
    else:
        config.read(f'default.ini', encoding='utf-8')
    logger.info('加载配置文件成功')


class TrayIcon:
    def __init__(self, icon_path, initial_labels):
        self.icon = Image.open(icon_path)
        self.labels = initial_labels
        self.menu = self.create_menu()
        self.tray_icon = pystray.Icon("app_name", self.icon, app_name, self.menu)

    def create_menu(self):
        menu_items = [item(label, self.on_label_clicked) for label in self.labels]
        menu_items.append(item("显示", self.on_show))
        menu_items.append(item("隐藏", self.on_hide))
        menu_items.append(item("显示信息面板", self.on_show_console, default=True, visible=False))
        menu_items.append(item("----------", self.on_label_clicked))

        menu_items.append(item(f"版本号 {version}", self.on_label_clicked))
        return menu_items

    def on_label_clicked(self, icon, item):
        logger.info(f"标签 {item.text} 被点击")

    def on_show_console(self, icon, item):
        logger.info(f"展示信息面板")

    def on_show(self):
        if driver_hwnd is None:
            return
        win32gui.ShowWindow(driver_hwnd, win32con.SW_RESTORE)
        left, top, right, bottom = win32gui.GetWindowRect(driver_hwnd)
        width = right - left
        height = bottom - top
        win32gui.SetWindowPos(driver_hwnd, win32con.HWND_TOPMOST, (centerX - width // 2), (centerY - height // 2),
                              width, height, win32con.SWP_SHOWWINDOW)
        win32gui.ShowWindow(driver_hwnd, win32con.SW_SHOW)

    def on_hide(self):
        if driver_hwnd is None:
            return
        win32gui.ShowWindow(driver_hwnd, win32con.SW_RESTORE)
        left, top, right, bottom = win32gui.GetWindowRect(driver_hwnd)
        width = right - left
        height = bottom - top
        win32gui.SetWindowPos(driver_hwnd, win32con.HWND_NOTOPMOST, 3000, 3000, width, height, win32con.SWP_SHOWWINDOW)
        win32gui.ShowWindow(driver_hwnd, win32con.SW_HIDE)

    def update_labels(self, new_labels):
        self.labels = new_labels
        self.menu = self.create_menu()  # 重新创建菜单
        self.tray_icon.menu = self.menu  # 更新托盘图标的菜单

    def update_title(self, title):
        self.tray_icon.title = title  # 更新托盘图标的菜单

    def run(self):
        self.tray_icon.run()


# 设置默认字体
default_font = ("Arial", 10)
note_font = ("Arial", 8)


class WindowSelectAccount:
    def __init__(self):
        self.root = None
        self.account_list = file_get_account_list()
        self.list_box = None
        self.entry = None
        self.menu = None

    def run(self):
        global default_font
        # 创建主窗口
        root = tk.Tk()
        self.root = root

        root.option_add("*Font", default_font)
        root.title(app_name)
        root.geometry("300x300")
        root['padx'] = 10  # 设置水平内边距
        root['pady'] = 10  # 设置垂直内边距

        # 创建文本描述区
        description_label = tk.Label(root, text="请选择对应的账号")
        description_label.pack(pady=10)  # 设置上边距

        # 创建列表框
        self.list_box = tk.Listbox(root, selectmode=tk.SINGLE)
        for item in self.account_list:
            self.list_box.insert(tk.END, item)
        # list_box.bind("<<ListboxSelect>>", on_select)  # 绑定选择事件
        self.list_box.bind("<Button-1>", self.on_select_click)  # 绑定鼠标左键双击事件
        self.list_box.bind("<Button-3>", self.on_right_click)  # 绑定鼠标右键点击事件
        # 将列表框放置在窗口中
        self.list_box.pack(fill=tk.BOTH, expand=True)

        # 创建右键菜单
        menu = tk.Menu(root, tearoff=0)
        self.menu = menu
        menu.add_command(label="删除", command=self.delete)  # 绑定菜单项的回调函数

        # log_text = tk.Text(root)
        # log_text.pack(pady=10)

        # 创建输入框和新增按钮
        add_button = tk.Button(root, text="开启新账号", command=self.new_item)
        add_button.pack(pady=5, side=tk.RIGHT)

        # 开启配置
        add_button = tk.Button(root, text="默认配置", command=self.open_default_config_window)
        add_button.pack(pady=5, side=tk.RIGHT)

        # 开启配置
        add_button = tk.Button(root, text="账户配置", command=self.open_config_window)
        add_button.pack(pady=5, side=tk.RIGHT)

        # 开启配置
        add_button = tk.Button(root, text="启动", command=self.start)
        add_button.pack(pady=5, side=tk.LEFT)

        # 计算窗口左上角的坐标使其居中
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        x = (screen_width - root.winfo_reqwidth()) / 2
        y = (screen_height - root.winfo_reqheight()) / 3
        root.geometry("+%d+%d" % (x, y))

        # 捕获窗口关闭事件
        root.protocol("WM_DELETE_WINDOW", self.on_closing)

        # 运行主循环
        root.mainloop()

    def on_closing(self):
        self.root.destroy()
        sys.exit(0)

    def on_select_click(self, event):
        global did, did_config_path
        selected_item = self.list_box.get(tk.ACTIVE)
        did = selected_item
        did_config_path = f'account/{did}'
        # 加载配置文件，如果自己账号没有，就用默认的

        # self.root.destroy()

    def on_right_click(self, event):
        # 获取鼠标点击位置
        x = event.x_root
        y = event.y_root
        # 获取当前选定的项
        index = self.list_box.nearest(event.y)
        self.list_box.selection_clear(0, tk.END)  # 清除之前的选定项
        self.list_box.selection_set(index)  # 设置当前选定的项
        self.list_box.activate(index)  # 激活当前选定的项
        # 显示菜单
        self.menu.post(x, y)

    def new_item(self):
        self.root.destroy()

    def open_default_config_window(self):
        SettingsWindow(self.root)

    def open_config_window(self):
        global did
        if did == '':
            # 创建一个窗口
            messagebox.showwarning("警告", "请选择一个账号")
            return
        SettingsWindow(self.root, did)


    def start(self):
        global did
        if did == '':
            # 创建一个窗口
            messagebox.showwarning("警告", "请选择一个账号")
            return
        # 加载配置文件
        load_config()
        self.root.destroy()

    def delete(self):
        result = tkinter.messagebox.askquestion("提示", "确定删除吗?")
        if result == "yes":
            # print("Performing action 1")
            selected_item = self.list_box.get(tk.ACTIVE)
            selected_index = self.list_box.curselection()
            if selected_index:
                self.list_box.delete(selected_index)
            file_delete_account(selected_item)
            global did
            did = ''


class SettingsWindow:
    def __init__(self, root, did=''):

        self.root = root
        self.settings_window = tk.Toplevel(self.root)
        self.settings_window.title(f"{'全局' if did == '' else did}配置")
        self.settings_window.grab_set()  # 设置为模态对话框

        self.did = did
        # self.config_fields = [
        #     ('Common', 'allow_tips'),
        #     ('Ai', 'ai_video_tip_prompt'),
        #     ('Search', 'search_keys'),
        #     ('View', 'view_rate'),
        #     ('Like', 'like_rate'),
        #     ('Collection', 'collection_rate'),
        #     ('Comment', 'comment_rate'),
        #     ('Comment', 'comment_style'),
        #     ('Video', 'video_time_play_max'),
        #     ('Common', 'max_type'),
        #     ('Common', 'max_count'),
        #     ('Common', 'begin_time')
        # ]

        self.default_config_path = 'default.ini'
        if self.did == '':
            self.config_path = 'default.ini'
        else:
            global did_config_path
            self.config_path = f'{did_config_path}/config.ini'
        self.configChecker = ConfigChecker(self.config_path, default_config_file=self.default_config_path)

        # 创建标签和文本框
        self.entries = []

        global default_font, note_font
        config_note_pad = (2, 15)

        # advanced_content = ttk.Frame(advanced_frame)
        # advanced_content.grid(row=0, column=0, padx=10, pady=5, sticky="nsew")

        # 创建一般组
        general_frame = ttk.LabelFrame(self.settings_window, text="标签")
        general_frame.grid(row=0, column=0, padx=10, pady=5, sticky="nsew")

        acc_row = 0
        section = 'Common'
        field = 'allow_tips'
        is_defaut, value = self.configChecker.check_field(section, field)
        label1 = ttk.Label(general_frame, text="我的标签")
        label1.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry1 = tk.Text(general_frame, height=4, width=30, wrap="word", name=f'{section.lower()}@{field}')
        entry1.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry1.insert('1.0', value)
        self.entries.append(entry1)
        text1 = ttk.Label(general_frame,
                          font=note_font,
                          text="该标签用于过滤，不符合该标签的视频，跳过\n多个标签用英文逗号隔开\n示例：美食,体育,情感\n如果不设置标签，则代表不限视频")
        text1.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        if did != '':
            check_var1 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry1, check_var1)
            check_button1 = ttk.Checkbutton(general_frame, text="默认", variable=check_var1,
                                            command=lambda: self.toggle_entry_state(entry1, check_var1),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button1.grid(row=acc_row, column=2, padx=10, pady=(3, 20), sticky="w")
        acc_row = acc_row + 2

        section = 'Ai'
        field = 'ai_video_tip_prompt'
        is_defaut, value = self.configChecker.check_field(section, field)
        label2 = ttk.Label(general_frame, text="判定标签")
        label2.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry2 = tk.Text(general_frame, height=4, width=30, wrap="word", name=f'{section.lower()}@{field}')
        entry2.insert('1.0', value)
        entry2.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        self.entries.append(entry2)
        text2 = ttk.Label(general_frame,
                          font=note_font,
                          text="该标签为ai判定标签，一定要包含“我的标签”\n用每个标签前边加#，多个标签用空格隔开\n示例：#美食 #体育 #电影 #游戏 #音乐 #情感 #育儿")
        text2.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        if self.did != '':
            check_var2 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry2, check_var2)
            check_button2 = ttk.Checkbutton(general_frame, text="默认", variable=check_var2,
                                            command=lambda: self.toggle_entry_state(entry2, check_var2),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button2.grid(row=acc_row, column=2, padx=10, pady=(3, 20), sticky="w")
        acc_row = acc_row + 2

        section = 'Search'
        field = 'search_keys'
        is_defaut, value = self.configChecker.check_field(section, field)
        label3 = ttk.Label(general_frame, text="长尾关键词")
        label3.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry3 = tk.Text(general_frame, height=10, width=30, name=f'{section.lower()}@{field}')  # 使用多行文本框
        entry3.insert('1.0',
                      value)
        entry3.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        self.entries.append(entry3)
        text3 = ttk.Label(general_frame,
                          font=note_font,
                          text="如果推荐频道经常刷不到带有我的标签的视频\n则开始搜索长尾关键词\n多个长尾关键词用逗号隔开，越多越好\n示例：新疆米粉排行榜,新疆米粉哪个牌子好吃,\n新疆炒米粉专用,新疆正宗粗米粉,新疆干米粉,\n美食米粉好吃")
        text3.grid(row=acc_row + 1, column=1, padx=10, pady=5, sticky="w")
        if self.did != '':
            check_var3 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry3, check_var3)
            check_button3 = ttk.Checkbutton(general_frame, text="默认", variable=check_var3,
                                            command=lambda: self.toggle_entry_state(entry3, check_var3),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button3.grid(row=acc_row, column=2, padx=10, pady=(3, 20), sticky="w")

        # text = ttk.Label(general_frame, text="点击获取长尾关键词", foreground="blue", cursor="hand2")
        # text.grid(row=6, column=1, padx=10, pady=config_note_pad, sticky="w")
        # text.bind("<Button-1>", self.get_search_keys)
        # https://www.douyin.com/aweme/v1/web/api/suggest_words/?query=%E6%96%B0%E7%96%86%E7%B1%B3%E7%B2%89&business_id=30125

        # 自定义一般组的样式
        style = ttk.Style()
        style.configure('General.TLabelframe.Label', background='lightblue')
        general_frame.configure(style='General.TLabelframe')

        # 创建高级组

        advanced_frame = ttk.LabelFrame(self.settings_window, text="任务")
        advanced_frame.grid(row=0, column=1, padx=10, pady=5, sticky="nsew")

        column1_with = 12
        column2_with = 60
        column3_with = 40

        acc_row = 0
        section = 'View'
        field = 'view_rate'
        is_defaut, value = self.configChecker.check_field(section, field)
        label4 = ttk.Label(advanced_frame, text="观看比", width=column1_with)
        label4.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry4 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry4.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry4.insert(acc_row, value)
        self.entries.append(entry4)
        if self.did != '':
            check_var4 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry4, check_var4)
            check_button4 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var4,
                                            command=lambda: self.toggle_entry_state(entry4, check_var4),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button4.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")

        text4 = ttk.Label(advanced_frame,
                          width=column2_with,
                          font=note_font,
                          text="标签匹配条件下，<点赞数>达到多少，按多少概率选择观看\n示例：0-0.01,5000-0.05,10000-0.1,100000-0.5,500000-1\n以上示例表示，如果点赞超过500000，则按照1的比率进行点赞操作（必点赞）\n如果点赞不到500000，但超过100000，则有0.5的概率点赞\n依次类推，注意符号")
        text4.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Like'
        field = 'like_rate'
        is_defaut, value = self.configChecker.check_field(section, field)
        label = ttk.Label(advanced_frame, text="点赞比", width=column1_with)
        label.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry.insert(0, value)
        self.entries.append(entry)
        if self.did != '':
            check_var = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry, check_var)
            check_button = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var,
                                           command=lambda: self.toggle_entry_state(entry, check_var),
                                           style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text = ttk.Label(advanced_frame,
                         width=column2_with,
                         font=note_font,
                         text="标签匹配条件下，<点赞率>达到多少，按多少概率点赞，规则同观看比")
        text.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Collection'
        field = 'collection_rate'
        is_defaut, value = self.configChecker.check_field(section, field)
        label5 = ttk.Label(advanced_frame, text="收藏比", width=column1_with)
        label5.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry5 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry5.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry5.insert(0, value)
        self.entries.append(entry5)
        if self.did != '':
            check_var5 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry5, check_var5)
            check_button5 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var5,
                                            command=lambda: self.toggle_entry_state(entry5, check_var5),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button5.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text5 = ttk.Label(advanced_frame,
                          width=column2_with,
                          font=note_font,
                          text="标签匹配条件下，<收藏数>达到多少，按多少概率收藏，规则同观看比")
        text5.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Comment'
        field = 'comment_rate'
        is_defaut, value = self.configChecker.check_field(section, field)
        label6 = ttk.Label(advanced_frame, text="评论比", width=column1_with)
        label6.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry6 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry6.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry6.insert(0, value)
        self.entries.append(entry6)
        if self.did != '':
            check_var6 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry6, check_var6)
            check_button6 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var6,
                                            command=lambda: self.toggle_entry_state(entry6, check_var6),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button6.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text6 = ttk.Label(advanced_frame,
                          font=note_font,
                          text="标签匹配条件下，<评论数>达到多少，按多少概率评论，规则同观看比")
        text6.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Comment'
        field = 'comment_style'
        is_defaut, value = self.configChecker.check_field(section, field)
        label7 = ttk.Label(advanced_frame, text="评论色彩", width=column1_with)
        label7.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry7 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry7.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry7.insert(0, value)
        self.entries.append(entry7)
        if self.did != '':
            check_var7 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry7, check_var7)
            check_button7 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var7,
                                            command=lambda: self.toggle_entry_state(entry7, check_var7),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button7.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text7 = ttk.Label(advanced_frame,
                          font=note_font,
                          text="示例1：风趣、幽默、简洁    示例2：正能量、正义")
        text7.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Video'
        field = 'video_time_play_max'
        is_defaut, value = self.configChecker.check_field(section, field)
        label8 = ttk.Label(advanced_frame, text="视频最大时长", width=column1_with)
        label8.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry8 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry8.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry8.insert(0, value)
        self.entries.append(entry8)
        if self.did != '':
            check_var8 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry8, check_var8)
            check_button8 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var8,
                                            command=lambda: self.toggle_entry_state(entry8, check_var8),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button8.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text8 = ttk.Label(advanced_frame,
                          font=note_font,
                          text="单位秒，视频时长超过该设置，则以该设置为准")
        text8.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Common'
        field = 'max_type'
        is_defaut, value = self.configChecker.check_field(section, field)
        label9 = ttk.Label(advanced_frame, text="任务类型", width=column1_with)
        label9.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry9 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry9.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry9.insert(0, value)
        self.entries.append(entry9)
        if self.did != '':
            check_var9 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry9, check_var9)
            check_button9 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var9,
                                            command=lambda: self.toggle_entry_state(entry9, check_var9),
                                            style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button9.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text9 = ttk.Label(advanced_frame,
                          font=note_font,
                          text="1-滑动次数（算广告、直播、不符合的标签）\n2-观看视频次数（除去广、直播、不符合的标签）\n3-成功点赞次数\n4-成功评论次数\n5-收藏数\n6-为执行时间，单位秒")
        text9.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Common'
        field = 'max_count'
        is_defaut, value = self.configChecker.check_field(section, field)
        label10 = ttk.Label(advanced_frame, text="任务目标", width=column1_with)
        label10.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry10 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry10.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry10.insert(0, value)
        self.entries.append(entry10)
        if self.did != '':
            check_var10 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry10, check_var10)
            check_button10 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var10,
                                             command=lambda: self.toggle_entry_state(entry10, check_var10),
                                             style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button10.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text10 = ttk.Label(advanced_frame,
                           font=note_font,
                           text="如果任务类型为6，该项设置为7200，则执行两小时任务完成")
        text10.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")
        acc_row = acc_row + 2

        section = 'Common'
        field = 'begin_time'
        is_defaut, value = self.configChecker.check_field(section, field)
        label11 = ttk.Label(advanced_frame, text="任务定时", width=column1_with)
        label11.grid(row=acc_row, column=0, padx=10, pady=5, sticky="w")
        entry11 = ttk.Entry(advanced_frame, width=column2_with, name=f'{section.lower()}@{field}')
        entry11.grid(row=acc_row, column=1, padx=10, pady=5, sticky="w")
        entry11.insert(0, value)
        self.entries.append(entry11)
        if self.did != '':
            check_var11 = tk.IntVar(value=1-int(is_defaut))
            self.toggle_entry_state(entry11, check_var11)
            check_button11 = ttk.Checkbutton(advanced_frame, text="默认", variable=check_var11,
                                             command=lambda: self.toggle_entry_state(entry11, check_var11),
                                             style=ttk.Style().configure('TCheckbutton', font=note_font))
            check_button11.grid(row=acc_row, column=2, padx=10, pady=5, sticky="w")
        text11 = ttk.Label(advanced_frame,
                           font=note_font,
                           text="示例：10,14。代表每日10点和14点执行，24小时制；留空代表立刻执行")
        text11.grid(row=acc_row + 1, column=1, padx=10, pady=config_note_pad, sticky="w")

        # 自定义高级组的样式
        style.configure('Advanced.TLabelframe.Label', background='lightgreen')
        advanced_frame.configure(style='Advanced.TLabelframe')

        # 创建保存按钮
        save_button = ttk.Button(self.settings_window, text="保存", command=self.save_config)
        save_button.grid(row=1, column=1, padx=10, pady=10)

        # 设置配置项之间的垂直间距
        # for child in general_frame.winfo_children():
        #     child.grid_configure(pady=20)

        # 设置窗口大小和位置
        self.settings_window.geometry("1100x820")
        self.settings_window.resizable(False, False)
        self.settings_window.geometry("+%d+%d" % (0, 0))

        # 设置行高度
        self.settings_window.grid_rowconfigure(0, weight=1)
        self.settings_window.grid_rowconfigure(1, weight=1)
        self.settings_window.grid_rowconfigure(2, weight=1)


    def save_config(self):
        # 在这里编写保存配置的逻辑
        for item in self.entries:
            names = item.winfo_name().split('@')
            section = names[0].capitalize()
            field = names[1]
            value = ''
            if isinstance(item, tk.Text):
                value = item.get("1.0", "end-1c")
            elif isinstance(item, ttk.Entry):
                value = item.get()
            state = str(item.cget('state'))
            if self.did == '':
                self.configChecker.default_config_file.set(section, field, value)
                with open(self.default_config_path, 'w', encoding='utf-8') as configfile:
                    self.configChecker.default_config_file.write(configfile)
            else:
                if state == 'normal':
                    if section in self.configChecker.config:
                        self.configChecker.config.set(section, field, value)
                    else:
                        self.configChecker.config.add_section(section)
                        self.configChecker.config.set(section, field, value)
                    with open(self.config_path, 'w', encoding='utf-8') as configfile:
                        self.configChecker.config.write(configfile)
                elif state == 'disabled':
                    if section in self.configChecker.config and field in self.configChecker.config[section]:
                        self.configChecker.config.remove_option(section, field)
                        with open(self.config_path, 'w', encoding='utf-8') as configfile:
                            self.configChecker.config.write(configfile)
        self.show_info("提示", "保存成功")
        return

    def show_info(self, title, content):
        top = tk.Toplevel()
        top.title(title)
        width = 200
        height = 100
        screen_width = top.winfo_screenwidth()
        screen_height = top.winfo_screenheight()
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        top.geometry(f"{width}x{height}+{x}+{y-100}")

        # top.geometry("200x100")  # 设置窗口大小
        label = tk.Label(top, text=content)
        label.pack()
        label.pack(expand=True, fill="both", padx=20, pady=20)  # 使用pack布局管理器居中Label
        top.resizable(False, False)
        top.focus_set()  # 将Toplevel窗口置于最前
        top.grab_set()  # 阻塞程序的执行
        top.wait_window()  # 等待Toplevel窗口关闭


    def toggle_entry_state(self, entry, check_var):
        if check_var.get() == 1:
            entry.config(state="disabled")
            entry.config(foreground='gray')
            # entry.config(background='lightgray')
        else:
            entry.config(state="normal")
            entry.config(foreground='black')
            # entry.config(background='white')

    def get_search_keys(self, event):
        # 在这里编写保存配置的逻辑

        pass


console_hwnd = None
driver = None
driver_window = None
driver_hwnd = None
driver_is_hide = False
driver_window_index = random.randint(100000, 999999)
driver_window_title = ''
process_off = False
thread_off = True
did = ''
did_config_path = ''
config = configparser.ConfigParser()


def start(tray_icon, scheduler_id):
    # 如果当前线程正在工作，则任何定时器都不能进入
    global thread_off
    if not thread_off:
        return
    thread_off = False
    logger.info('正在拉起主程序，预计需要1分钟')

    global driver, config
    driver = start_create_driver()

    # 加载首页
    start_load(driver)

    # 清理文件
    logger.info('正在清理文件...')
    clear_tmp_and_rust(logger, driver)



    # 获取个人昵称
    my_account_nickname = get_my_account_nickname(driver)
    tray_icon.update_title(my_account_nickname)

    # 检查账户
    my_account_did = get_my_account_did(driver)
    if my_account_did != did:
        logger.info('该账户不匹配！')
        off_thread()
        return

    status, _ = web.user_check({
        'did': did
    })
    if not status:
        logger.info('该用户没有权限！')
        off_thread()
        return

    # 查看私信
    # move_notice(driver)

    # 尝试打开侧边栏5次
    start_right(driver)

    time.sleep(10)

    acc_next = 0
    acc_view = 0
    acc_like = 0
    acc_comment = 0
    acc_collection = 0
    acc_share = 0
    acc_unlike = 0
    acc_unlike_tmp = 0
    acc_jump_recommend = 0
    acc_search = 0
    # 时间
    time_show_panel = 2
    start_timestamp = int(time.time())
    while True:
        # 检查线程
        if thread_off:
            off_thread()
            return

        # 检查浏览器
        try:
            title = driver.title
        except WebDriverException:
            off_thread()
            return

        # 检测主进程是否被关闭
        if process_off:
            off_thread()
            return

        # 检查账户
        status, _ = web.user_check({
            'did': did
        })
        if not status:
            logger.info('该用户没有权限！')
            off_thread()
            return

        # 检查是否完成任务
        # logger.info(
        #     f'###### acc_next:{acc_next} acc_view:{acc_view} acc_like:{acc_like} acc_comment:{acc_comment} acc_collection:{acc_collection} acc_next:{acc_share}')
        max_type = config.getint('Common', 'max_type', fallback=1)
        max_count = config.getint('Common', 'max_count', fallback=100)
        should_over = False
        if max_type == 1 and max_count < acc_next:
            should_over = True
        elif max_type == 2 and max_count < acc_view:
            should_over = True
        elif max_type == 3 and max_count < acc_like:
            should_over = True
        elif max_type == 4 and max_count < acc_comment:
            should_over = True
        elif max_type == 5 and max_count < acc_collection:
            should_over = True
        elif max_type == 6 and max_count < (int(time.time()) - start_timestamp):
            should_over = True
        if should_over:
            # 保存浏览器缓存，这步如果保存则可能要验证登录
            # file_runtime_save()
            # 结束线程
            off_thread()
            # 该定时器下一次
            if scheduler_id is not None:
                scheduler_next_job(scheduler_id)
            logger.info('该时段任务完成，等待下一个目标!')
            return

        # 更新ui
        tray_icon.update_labels(create_panel(acc_next, acc_view, acc_like, acc_comment, acc_collection, acc_captcha,
                                             int(time.time()) - start_timestamp, acc_unlike, my_account_nickname,
                                             acc_jump_recommend, acc_search))

        # 检测二次登录
        # if not start_login_runtime(driver):
        #     logger.info('用密码登录失败')
        #     time.sleep(5)
        #     continue


        # 检测二次验证
        for i in range(0, 10):
            if check_captcha_container_mask(driver):
                break
            time.sleep(3)

        # 检测不符合标签的重新点击推荐
        if acc_unlike_tmp > config.getint('Common', 'common_unlike_acc_limit', fallback=10):
            logger.info('点击了推荐，相当于系统重新推荐')
            jump_recommend(driver)
            acc_jump_recommend = acc_jump_recommend + 1
            acc_unlike_tmp = 0
            time.sleep(5)

        if acc_jump_recommend > config.getint('Common', 'common_jump_recommend_limit', fallback=10):
            logger.info('去搜索了')
            search_keys(driver)
            acc_search = acc_search + 1
            acc_jump_recommend = 0

            # 实时保存浏览器环境
            # file_runtime_save()

        icon = f"video_{acc_next}"
        logger.info(f'============================ {icon} 开始新的视频 ============================')
        show_next_video(driver)
        acc_next = acc_next + 1

        time.sleep(time_show_panel)

        if check_live(driver):
            logger.info('直播跳过！')
            time.sleep(2)
            continue

        try:
            video_desc, is_ad, is_online = get_video_desc(driver)
            common_tip_title = video_desc
            if config.getint('Common', 'common_tip_title', fallback=0) == 0:
                common_tip_title = ''

            if is_ad or is_online:
                continue

            like_count = get_like_count(driver)
            comment_count = get_comment_count(driver)
            collection_count = get_collection_count(driver)
            share_count = get_share_count(driver)
            video_id = get_video_id(driver)
            account_href = get_account_href(driver)

            # 视频播放最大时长
            video_duration = get_video_duration(driver)

            logger.info(
                f'[is_ad:{is_ad} is_online:{is_online} video_desc:{video_desc} like_count:{like_count} comment_count:{comment_count} like_count:{like_count} '
                f'collection_count:{collection_count} share_count:{share_count} video_id:{video_id} video_duration:{video_duration}  account_href:{account_href}')

            # 设置单视频播放时间，如果设置了最大时长
            video_time_play_max = config.getint('Video', 'video_time_play_max', fallback=0)
            if video_time_play_max > 0:
                if 0 < video_time_play_max < 30:
                    video_time_play_max = random.randint(3 * 60, 4 * 60)
                # 最大时长不能固定，应该加上一个随机数
                video_time_play_max = video_time_play_max + random.randint(0, 30)
                # 如果视频时长大于video_time_play_max，则以video_time_play_max为准
                if video_duration > video_time_play_max:
                    video_duration = video_time_play_max

            # 如果时间少于30秒，就多看一边
            if video_duration < 10:
                remain_duration = video_duration * 2 - time_show_panel
            elif video_duration < 20:
                remain_duration = video_duration * 3 - time_show_panel
            elif video_duration < 30:
                remain_duration = video_duration * 2 - time_show_panel
            else:
                remain_duration = video_duration - time_show_panel

            '''
            获取标签
            '''
            ai_tips = None
            # if config.getint('Common', 'common_tip', fallback=0) == 1:
            if config.get('Common', 'allow_tips', fallback='').strip() != '':
                ai_comment_start_timestamp = int(time.time())
                ai_tips = get_video_tip(driver, common_tip_title)
                ai_comment_end_timestamp = int(time.time())
                remain_duration = remain_duration - (ai_comment_end_timestamp - ai_comment_start_timestamp)
            '''
            开始观看视频
            '''
            if ai_tips is None or check_by_video_tip(driver, config.get('Common', 'allow_tips', fallback=''),
                                                     ai_tips):
                acc_view = acc_view + 1
                acc_unlike_tmp = max(0, acc_unlike_tmp - 1)
                if check_by_count(config.get('View', 'view_rate', fallback='0-0'), like_count) is False:
                    logger.info('View 随机概率未通过')
                    continue
            else:
                logger.info('View tip未通过')
                acc_unlike = acc_unlike + 1
                acc_unlike_tmp = acc_unlike_tmp + 1
                continue

            '''
            生成评论
            '''
            ai_comment_start_timestamp = int(time.time())
            comment = ''
            if ai_tips is None or check_by_video_tip(driver, config.get('Common', 'allow_tips', fallback=''),
                                                     ai_tips):
                if check_by_count(config.get('Comment', 'comment_rate', fallback='0-0'), comment_count):
                    if coin(config.getfloat('Comment', 'comment_gpt_rate', fallback=0.0)):
                        logger.info('从gpt生成评论')
                        comment = get_comment_from_gpt(driver, common_tip_title)
                    else:
                        logger.info('从本地评论库中找评论')
                        comment = get_comment_from_local(driver)
                else:
                    logger.info('Comment 随机概率未通过')
            else:
                logger.info('Comment tips未通过')
            ai_comment_end_timestamp = int(time.time())

            # 如果不需要评论，则视频不需要重复看
            if comment == '':
                remain_duration = video_duration - time_show_panel
                if video_duration < 13:
                    remain_duration = video_duration * 2 - time_show_panel
                remain_duration = remain_duration - (ai_comment_end_timestamp - ai_comment_start_timestamp)
            else:
                remain_duration = remain_duration - (ai_comment_end_timestamp - ai_comment_start_timestamp)

            # 看了一半，然后随机点赞、收藏、评论，留10秒钟给大模型返回评论
            time_view = remain_duration - int(remain_duration * 0.5) + random.randint(5, int(remain_duration * 0.5)) - 5
            time.sleep(time_view)
            remain_duration = remain_duration - time_view

            '''
            开始评论
            '''
            if comment != '':
                submit_comment(driver, comment)
                acc_comment = acc_comment + 1
                logger.info('已评论')
                time.sleep(1)
                remain_duration = remain_duration - 1

            '''
            开始点赞
            '''
            if ai_tips is None or check_by_video_tip(driver, config.get('Common', 'allow_tips', fallback=''),
                                                     ai_tips):
                if check_by_count(config.get('Like', 'like_rate', fallback='0-0'), like_count):
                    add_like_count(driver)
                    acc_like = acc_like + 1
                    logger.info('已点赞')
                    time.sleep(1)
                    remain_duration = remain_duration - 1
                else:
                    logger.info('Like 随机概率未通过')
            else:
                logger.info('Like tips未通过')

            '''
            开始收藏
            '''
            if ai_tips is None or check_by_video_tip(driver,
                                                     config.get('Common', 'allow_tips', fallback=''),
                                                     ai_tips):
                if check_by_count(config.get('Collection', 'collection_rate', fallback='0-0'), collection_count):
                    add_collection_count(driver)
                    acc_collection = acc_collection + 1
                    logger.info('已收藏')
                    time.sleep(1)
                    remain_duration = remain_duration - 1
                else:
                    logger.info('Collection 随机概率未通过')
            else:
                logger.info('Collection tips未通过')

            '''
            全部动作完成，继续看一会视频
            '''
            time.sleep(remain_duration)

            '''
            随机上翻
            '''
            if coin(config.getfloat('Video', 'video_prev_rate', fallback=0)):
                logger.info('随机概率通过 可以上翻')
                show_prev_video(driver)
                time.sleep(2)
                video_desc, is_ad, is_online = get_video_desc(driver)
                if not is_ad and not is_online:
                    # 随机看看上一个
                    time.sleep(random.randint(5, 30))
                show_next_video(driver)
                time.sleep(2)

            '''
            随机进入个人页面
            '''
            if coin(config.getfloat('User', 'user_rate', fallback=0)):
                time.sleep(2)
                logger.info('随机概率通过 可以进入个人主页')
                show_user_works_panel(driver)
                time.sleep(5)
                jump_user_index(driver)
                time.sleep(5)
                # 焦点切换成新弹出tab
                current_window = driver.current_window_handle
                all_windows = driver.window_handles
                for window in all_windows:
                    if window != current_window:
                        driver.switch_to.window(window)
                        break
                # 新tab，做一些事
                driver.close()

                # tab切换到第一窗口
                time.sleep(5)
                for window in all_windows:
                    driver.switch_to.window(window)
                    break
                time.sleep(5)
                show_comment_panel(driver)

            # if acc_next % 10 == 0 and setting.getint('System', 'save_browser_runtime', fallback=0) == 1:
            #     file_runtime_save()
        except ValueError as e:
            if 'invalid literal for int() with base 10: ''' in str(e):
                window_restore(backend=driver_is_hide)
                if setting.getint('System', 'element_error_log', fallback=0) == 1:
                    logger.warning(get_error_log())


        except Exception as e:
            if setting.getint('System', 'element_error_log', fallback=0) == 1:
                logger.warning(get_error_log())
            time.sleep(2)


def start_right(driver):
    # 尝试打开侧边栏5次
    open_right_times = 0
    while True:
        check_captcha_container_mask(driver)
        if open_right_times > 30:
            break
        time.sleep(2)
        try:
            logger.info(f'尝试打开侧边栏{open_right_times + 1}次')
            show_right_bar(driver)
            break
        except Exception as e:
            if setting.getint('System', 'element_error_log', fallback=0) == 1:
                logger.warning(get_error_log())
            show_next_video(driver)
        open_right_times = open_right_times + 1
        # 每逢5次就加载一次
        if open_right_times % 5 == 0:
            logger.info(f'重新加载首页{open_right_times + 1}次')
            start_load(driver)

    time.sleep(5)
    # 尝试打开评论区域5次
    for i in range(5):
        time.sleep(2)
        try:
            logger.info(f'尝试打开评论区{i + 1}次')
            show_comment_panel(driver)
            break
        except Exception as e:
            if setting.getint('System', 'element_error_log', fallback=0) == 1:
                logger.warning(get_error_log())
            show_next_video(driver)


def start_login(driver):
    user_config_path = fuzzy_search_folder_by_time(tempfile.gettempdir(), 'rust_')
    notice_is_show = False

    while True:
        if thread_off:
            return False, False
        time.sleep(1)
        try:
            content = driver.find_element(By.ID, 'douyin-header').text
        except Exception:
            if not notice_is_show:
                notice_is_show = True
                logger.info('未登录抖音，等待登录中...')
            continue
        if '登录' in content:
            if not notice_is_show:
                notice_is_show = True
                logger.info('未登录抖音，等待登录中...')
            continue
        if not notice_is_show:
            return True, False
        time.sleep(2)
        global did, did_config_path, config_path
        did = get_my_account_did(driver)
        status, _ = web.user_check({
            'did': did
        })
        if not status:
            logger.info(f'{did} 该用户没有权限！')
            sys.exit(0)

        did_config_path = f'account/{did}'
        user_config_path_new = f'{did_config_path}/browse-config'

        # 检查相关路径及文件完整性
        start_check_path_and_file()
        logger.warning("/****** 非常重要 ******/")
        logger.warning('\n等待手动保存登录状态，这步手动操作非常重要\n操作方法：鼠标放到浏览器右上角头像，弹出个人资料，最下方有个保存登录信息，请点开，输入验证码则输入验证码\n如果碰到验证码发送频繁，则稍等一会尝试点开。')
        logger.warning("/****** ****** ******/")
        time.sleep(2)
        input("以上如果您已手动执行完成，请敲回车，程序将继续执行，如果没反应，多敲几次...")

        create_user_agent(did, user_agent)
        logger.info('正在保存浏览器头部...')
        shutil.rmtree(user_config_path_new, ignore_errors=True)
        logger.info('正在清空原浏览器配置...')
        time.sleep(5)
        logger.info('正在复制新浏览器配置...')

        shutil.copytree(user_config_path, user_config_path_new,
                        ignore=shutil.ignore_patterns('parent.lock', 'chrome'))

        return True, True


def start_login_runtime(driver):
    user_config_path = fuzzy_search_folder_by_time(tempfile.gettempdir(), 'rust_')
    logged = True

    try:
        element = driver.find_element(By.CLASS_NAME, 'web-login-trusted__other-login')
        element = element.find_element_by_xpath('.//span[1]')
        element.click()

        # 说明已经需要再次登陆了
        logger.info('弹出快捷登录，采用密码登录')
        logged = False

        time.sleep(5)

        element = driver.find_element(By.CLASS_NAME, 'web-login-tab-list')
        element = element.find_element_by_xpath('.//li[3]')
        element.click()

        time.sleep(3)
        login_mobile = config.get('Common', 'login_mobile', fallback='')
        login_password = config.get('Common', 'login_password', fallback='')
        if login_mobile == '' or login_password == '':
            logger.warning('未配置手机号和密码，在尝试用密码登录时可能会引起登录失败')
            return False
        element = driver.find_element(By.CLASS_NAME, 'web-login-account-password__account-input-wrapper')
        element = element.find_element_by_xpath('.//input[@class="web-login-normal-input__input"]')
        element.send_keys(login_mobile)

        time.sleep(2)

        element = driver.find_element(By.CLASS_NAME, 'web-login-account-password__password-input-wrapper')
        element = element.find_element_by_xpath('.//input[@type="password"]')
        element.send_keys(login_password)

        time.sleep(2)

        element = driver.find_element(By.CLASS_NAME, 'web-login-account-password__button-wrapper')
        element = element.find_element_by_xpath('.//button[1]')
        element.click()

        # 登录完成，则不需要登陆了
        logged = True
        time.sleep(5)

        check_captcha_container_mask(driver)
        time.sleep(5)
        logger.info('再次单击登录')
        element = driver.find_element(By.CLASS_NAME, 'web-login-account-password__button-wrapper')
        element = element.find_element_by_xpath('.//button[@type="submit"]')
        mouse = ActionChains(driver)
        mouse.move_to_element(element).click().perform()

        # global did, did_config_path, config_path
        # did = get_my_account_did(driver)
        # status, _ = web.user_check({
        #     'did': did
        # })
        # if not status:
        #     logger.info(f'{did} 该用户没有权限！')
        #     sys.exit(0)
        #
        # did_config_path = f'account/{did}'
        user_config_path_new = f'{did_config_path}/browse-config'

        shutil.rmtree(user_config_path_new, ignore_errors=True)
        logger.info('正在清空原浏览器配置...')
        time.sleep(5)
        logger.info('正在复制新浏览器配置...')
        shutil.copytree(user_config_path, user_config_path_new,
                        ignore=shutil.ignore_patterns('parent.lock', 'chrome'))

        # start_right(driver)
    except Exception:
        logger.info(get_error_log())
    return logged


def start_check_path_and_file():
    user_config_path_new = f'{did_config_path}/browse-config'
    # 创建用户资料文件夹
    if not os.path.exists(did_config_path):
        os.makedirs(did_config_path)
        logger.info(f"创建用户资料 {did_config_path} 成功")
    logger.info(f"检查用户资料文件成功")
    # 创建用户浏览器资料文件夹

    if not os.path.exists(user_config_path_new):
        os.makedirs(user_config_path_new)
        logger.info(f"创建用户浏览器资料文件夹 {user_config_path_new} 成功")
    logger.info(f"检查用户浏览器资料文件成功")

    return True

user_agent=''
def start_create_driver():
    global driver
    browse_config_path = f'{did_config_path}/browse-config'
    if os.path.exists(browse_config_path):
        firefoxProfile = webdriver.FirefoxProfile(f'{did_config_path}/browse-config')
    else:
        firefoxProfile = webdriver.FirefoxProfile()

    # firefoxProfile = webdriver.FirefoxProfile()

    # 以下这两项在selenium原始文件中修改，路径为selenium/webdriver_prefs.json
    # firefoxProfile.set_preference("browser.link.open_newwindow", 3) # 新tab打开跳转链接，而不是新窗口
    # firefoxProfile.set_preference("browser.tabs.loadInBackground", False) # 打开新tab直接焦点切换过去
    global user_agent
    user_agent = get_user_agent(did)
    firefoxProfile.set_preference('general.useragent.override', user_agent)
    driver = webdriver.Firefox(firefox_binary="firefox/firefox.exe", firefox_profile=firefoxProfile)
    return driver


def start_load(driver):
    try:
        driver.set_page_load_timeout(120)
        driver.get('https://www.douyin.com')
        # search_keys(driver)
        # time.sleep(1000)
        # driver.get("javascript:alert('Hello, this is a JavaScript alert!');")
        # 设置网页内容
        # html_content = """
        # <!DOCTYPE html>
        # <html>
        # <meta charset="UTF-8">
        # <head>
        #     <title></title>
        # </head>
        # <body>
        #     <h1>任务完成，正在等待下一个任务；</h1>
        # </body>
        # </html>
        # """
        # data_url = "data:text/html," + html_content
        # driver.get(data_url)
        # time.sleep(190000)
    except Exception:
        if setting.getint('System', 'element_error_log', fallback=0) == 1:
            logger.warning(get_error_log())
        logger.info('超时，继续')

    # if not start_login_runtime(driver):
    #     logger.info('程序启动，用密码登录失败')
    # 获取浏览器的窗口标识
    time.sleep(10)
    source_title = driver.title
    driver.execute_script(f"document.title = '{driver.title + str(driver_window_index)}'")
    time.sleep(1)
    window_get_window()
    driver.execute_script(f"document.title = '{source_title}'")
    window_restore()

    logger.info('首页加载完毕！')
    logger.info('检查登录状态！')
    is_login_success, is_login_this_time = start_login(driver)
    if not is_login_success:
        logger.info('尝试登录失败！')
        off()

    if not is_login_this_time and not start_check_path_and_file():
        logger.info('账户文件有丢失，重新登录！')
        off()

    time.sleep(10)

    # 检测二次验证

    # for i in range(0, 10):
    #     if check_second_verify_mask(driver):
    #         break

    # 检测10次验证码
    for i in range(0, 10):
        if check_captcha_container_mask(driver):
            break
        time.sleep(3)





def off():
    global process_off
    try:
        # 浏览器关闭，
        driver.quit()
    except:
        pass

    try:
        urllib3.PoolManager().clear()
    except:
        pass

    process_off = True
    sys.exit(0)


def off_thread():
    try:
        # 浏览器关闭，
        driver.quit()
    except:
        pass

    try:
        urllib3.PoolManager().clear()
    except:
        pass
    global thread_off
    thread_off = True
    logger.info('线程退出.')


def window_restore(front=False, backend=False):
    win32gui.ShowWindow(driver_hwnd, win32con.SW_RESTORE)
    if backend:
        win32gui.SetWindowPos(driver_hwnd, win32con.HWND_BOTTOM, 0, 0, 0, 0,
                              win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_NOACTIVATE)
    if front:
        win32gui.SetWindowPos(driver_hwnd, win32con.HWND_NOTOPMOST, 0, 0, 0, 0,
                              win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_NOACTIVATE)


def window_get_window():
    # 获取所有打开的窗口
    global driver_hwnd, driver_window_index
    titles = gw.getAllTitles()
    for title in titles:
        if str(driver_window_index) in title:
            driver_window = gw.getWindowsWithTitle(title)[0]
            driver_hwnd = driver_window._hWnd
            logger.info(f'获取窗口信息{driver_window} 其中句柄为{driver_hwnd}')
            return


def file_get_account_list():
    # 指定要查看的文件夹路径
    folder_path = 'account'

    # 使用os.listdir()方法列出文件夹中的所有子文件
    return os.listdir(folder_path)


def file_get_one_comment_by_weight():
    try:
        return get_one_comment_by_weight('comment.csv', f'{did_config_path}/comment.csv')
    except Exception as e:
        logger.warning(get_error_log())
        return ''


def file_delete_account(did):
    logger.info(f'正在删除账号 {did}')
    shutil.rmtree(f'account/{did}')
    logger.info(f'删除账号 {did} 成功')


def file_runtime_save():
    user_config_path = fuzzy_search_folder_by_time(tempfile.gettempdir(), 'rust_')
    did_config_path = f'account/{did}'
    user_config_path_new = f'{did_config_path}/browse-config'
    shutil.rmtree(user_config_path_new, ignore_errors=True)
    logger.info('正在清空原浏览器配置...')
    time.sleep(5)
    logger.info('正在复制新浏览器配置...')
    shutil.copytree(user_config_path, user_config_path_new,
                    ignore=shutil.ignore_patterns('parent.lock', 'chrome'))


def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False


def scheduler_next_job(scheduler_id):
    job_detail = scheduler.get_job(scheduler_id)
    # minute = 0
    hour = '*'
    for index, item in enumerate(job_detail.trigger.fields):
        # if index == 6:
        #     minute = int(str(item))
        if index == 5:
            hour = int(str(item))
    # print('minute', minute)
    # print('hour', hour)
    scheduler_refresh_job(hour=hour, minute=random.randint(0, 30), scheduler_id=scheduler_id)


def scheduler_refresh_job(hour, minute, scheduler_id=None):
    if scheduler.get_job(scheduler_id) is not None:
        scheduler.remove_job(scheduler_id)
    scheduler.add_job(start, 'cron', hour=hour, minute=minute, args=[tray_icon, scheduler_id],
                      id=scheduler_id)


if __name__ == '__main__':
    # if not is_admin():
    #     pyautogui.alert(f'{app_name}必须以管理员身份运行. 请点击右键以管理员身份运行。')
    #     sys.exit(0)
    # 你可以选择在这里退出应用程序或者尝试以管理员权限重新运行
    logger.info('程序即将启动，请不要关闭该窗口')

    # 弹窗选择账户
    windowSelectAccount = WindowSelectAccount()
    windowSelectAccount.run()

    # 获取命令行窗口句柄
    kernel32 = ctypes.windll.kernel32
    GetConsoleWindow = kernel32.GetConsoleWindow
    console_hwnd = GetConsoleWindow()

    # 当然，线程还会读取一遍，这里只是为了定时器和线程的选择，如果当前第一次登录，则可能要按照default.ini启动时间了
    config.read(['setting.ini', 'default.ini', f'{did_config_path}/config.ini'], encoding='utf-8')

    # 右下角
    tray_icon = TrayIcon("favicon.ico", create_panel())

    scheduler = BlockingScheduler()
    # scheduler_refresh_job(hour=22, minute=52, scheduler_id='job_index_1')
    begin_time = config.get('Common', 'begin_time', fallback='')
    # did_config_path的条件是，如果是第一次登录
    if begin_time == '' or did_config_path == '':
        main_thread = threading.Thread(target=start, args=[tray_icon, None])
        main_thread.start()
    else:
        begin_time = begin_time.split(',')
        # scheduler_refresh_job(hour=0, minute=13, scheduler_id=f'job_index_{2323}')
        # scheduler_refresh_job(hour=0, minute=19, scheduler_id=f'job_index_{2330}')
        for hour in begin_time:
            minute = random.randint(0, 10)
            logger.info(f'{hour}:{minute}分将启动一个任务')
            scheduler_refresh_job(hour=hour, minute=random.randint(0, 10), scheduler_id=f'job_index_{hour}')
        scheduler.start()

    tray_icon.run()
